package top.lishuoboy.shiro.realm;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import top.lishuoboy.dependency.base.json.HuJsonUtil;
import top.lishuoboy.shiro.bean.User;

import java.util.Arrays;
import java.util.List;

/**
 * 4.5 自定义Realm领域，将认证数据来源从配置文件shiro.ini改为从数据库获取
 *
 * @author lishuoboy
 * @date 2022/2/15 13:26
 */
@Slf4j
public class CustomizeMd5Realm extends AuthorizingRealm {
    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("== 授权 doGetAuthorizationInfo==================");

        String primaryPrincipal = (String) principals.getPrimaryPrincipal();
        // 身份信息(用户名) primaryPrincipal==zhangsan
        log.debug("身份信息(用户名) primaryPrincipal=={}", primaryPrincipal);

//        Set<String> realmNameSet = principals.getRealmNames();
        // 使用的领域名字 realmNames==["top.lishuoboy.shiro.realm.CustomizeMd5Realm_0"]
//        log.debug("使用的领域名字 realmNames=={}", HuJsonUtil.toJsonStr(realmNameSet));

        // 创建“简单的授权信息”对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        // 模拟 将数据库中查询角色信息赋值给权限对象
        // select role from n个table where 省略一万个字 and name='${primaryPrincipal}';
        List<String> roleList = Arrays.asList("admin", "user", "super");
        simpleAuthorizationInfo.addRoles(roleList);

        // 模拟将数据库中查询权限信息赋值个权限对象
        // select permission from n个table where 省略一万个字 and name='${primaryPrincipal}';
        simpleAuthorizationInfo.addStringPermission("user:*:01");
        simpleAuthorizationInfo.addStringPermission("product:add");  //相当于 product:add:*
//        simpleAuthorizationInfo.addStringPermissions(null); //

        return simpleAuthorizationInfo;
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        log.info("== 认证 doGetAuthenticationInfo==================");
        //在token中获取用户名
        String principal = (String) token.getPrincipal();
        Object credentials = token.getCredentials();
        log.debug("用户输入的用户名 principal=={}", principal);
        log.debug("用户输入的密码  credentials=={}", HuJsonUtil.toJsonStr(credentials));
        // 模拟 根据身份信息使用jdbc mybatis查询数据库中的 用户名、1024次的MD5密码/盐 等 用户信息
//        select * from user where name = 'principal'
        User user = new User().setName("zhangsan").setPwd("45c71c907abdbf45044b9e163a9a47d1").setSalt("salt!@#");

        if (user != null && user.getName().equals(principal)) {
            //参数1: 数据库用户名  参数2:数据库md5+salt之后的密码  参数3:注册时的随机盐  参数4:realm的名字
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, user.getPwd(), ByteSource.Util.bytes(user.getSalt()), this.getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}
